/**
 *
 * @param {Function} reducer
 * @param {object} preloadedState 初始状态
 * @param {Function} enhancer 中间件
 * @returns
 */
export function createStore(reducer, preloadedState, enhancer) {
  // 增强dispatch函数 start
  if (typeof preloadedState === "function" && typeof enhancer === "undefined") {
    enhancer = preloadedState;
    preloadedState = undefined;
  }
  if (typeof enhancer !== "undefined") {
    // 判断 enhancer 不是一个函数
    if (typeof enhancer !== "function") {
      // 抛出一个异常 (enhancer 必须是一个函数)
      throw new Error("Expected the enhancer to be a function.");
    }
    // 调用 enhancer ,返回一个增强版的 store creator
    return enhancer(createStore)(reducer, preloadedState);
    // 函数柯里化
    // function enhancer(createStore) {
    //     return (reducer, preloadedState) => {
    //         return createStore(reducer, preloadedState)
    //     }
    // }
  }
  let subscribe_fns = new Set();
  let state = preloadedState;
  function getState() {
    return state;
  }
  function subscribe(listener_fn) {
    subscribe_fns.add(listener_fn);
    //  返回一个取消订阅的方法
    return function unSubscribe() {
      const index = subscribe_fns.indexOf(listener_fn);
      subscribe_fns.splice(index, 1);
    };
  }
  function dispatch(action) {
    state = reducer(state, action);
    for (let fn of subscribe_fns) {
      fn();
    }
  }

  // 初始化state
  dispatch({});

  return {
    getState,
    subscribe,
    dispatch,
  };
}

// 使用方法如下

// import { createStore } from 'redux'

/**
 * 这是一个 reducer 函数：接受当前 state 值和描述“发生了什么”的 action 对象，它返回一个新的 state 值。
 * reducer 函数签名是 : (state, action) => newState
 *
 * Redux state 应该只包含普通的 JS 对象、数组和原语。
 * 根状态值通常是一个对象。 重要的是，不应该改变 state 对象，而是在 state 发生变化时返回一个新对象。
 *
 * 你可以在 reducer 中使用任何条件逻辑。 在这个例子中，我们使用了 switch 语句，但这不是必需的。
 * 
 */
function counterReducer(state = { value: 0 }, action) {
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

// 创建一个包含应用程序 state 的 Redux store。
// 它的 API 有 { subscribe, dispatch, getState }.
let store = createStore(counterReducer)

// 你可以使用 subscribe() 来更新 UI 以响应 state 的更改。
// 通常你会使用视图绑定库（例如 React Redux）而不是直接使用 subscribe()。
// 可能还有其他用例对 subscribe 也有帮助。

store.subscribe(() => console.log(store.getState()))

// 改变内部状态的唯一方法是 dispatch 一个 action。
// 这些 action 可以被序列化、记录或存储，然后再重放。
store.dispatch({ type: 'counter/incremented' })
// {value: 1}
store.dispatch({ type: 'counter/incremented' })
// {value: 2}
store.dispatch({ type: 'counter/decremented' })
// {value: 1}
